#include "sexp.h"
#include "symtab.h"

static symtabADT variableTable;

struct sExpCDT {
	sExpTypeT type;
	union {
		int number;
		string atom;
		struct {
			sExpADT car;
			sExpADT cdr;
		} dottedPair;
	} value;
};

void InitSymbolTable(void)
{
    variableTable = NewSymbolTable();
}

sExpTypeT SExpType(sExpADT sx)
{
	return sx->type;
}

sExpADT Car(sExpADT sx)
{
	if(sx->type == DtprType)
		return sx->value.dottedPair.car;
	else
		Error("S-expression is not a dotted pair");
}

sExpADT Cdr(sExpADT sx)
{
	if(sx->type == DtprType)
		return sx->value.dottedPair.cdr;
	else
		Error("S-expression is not a dotted pair");
}

sExpADT Cons(sExpADT car, sExpADT cdr)
{
	sExpADT sx;
	sx = New(sExpADT);

	sx->type = DtprType;
	sx->value.dottedPair.car = car;
	sx->value.dottedPair.cdr = cdr;

	return sx;
}

sExpADT StringToAtom(string name)
{
	sExpADT sx;
	sx = New(sExpADT);

	sx = Lookup(variableTable, name);

	if(sx == UNDEFINED)
	{
		sx->type = AtomType;
		sx->value.atom = name;

		Enter(variableTable, name, (void*)sx);
	}

	return sx;
}

string AtomToString(sExpADT atom)
{
	if(atom->type == AtomType)
		return atom->value.atom;
	else
		Error("S-expression is not an atom");
}

sExpADT NumberToSExp(int n)
{
	sExpADT sx;

	sx = New(sExpADT);

	sx->type = NumberType;
	sx->value.number = n;

	return sx;
}

int SExpToNumber(sExpADT sx)
{
	if(sx->type == NumberType)
		return sx->value.number;
	else
		Error("S-expression is not a number.");
}
